﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System.Configuration;
using Communergy.NationalGridDataServices;
using System.Diagnostics;


namespace NationalGridMonitor
{
    public class NationalGridSystemTrayApp : Form
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        public static void Main()
        {
            Application.Run(new NationalGridSystemTrayApp());
        }

        protected override void OnLoad(EventArgs e)
        {
            Visible = false; // Hide form window.
            ShowInTaskbar = false; // Remove from taskbar.

            base.OnLoad(e);
        }

        private void OnExit(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private decimal lowerLimitDefault = 0.5M;
        private decimal upperLimitDefault = 0.7M;


        private NotifyIcon trayIcon;
        private ContextMenu trayMenu;
        bool isLive = true;

        public NationalGridSystemTrayApp()
        {
            Trace.WriteLine("Setting up context menu");
            trayMenu = new ContextMenu();
            trayMenu.MenuItems.Add("Exit", OnExit);

            Trace.WriteLine("Setting up system tray");
            trayIcon = new NotifyIcon();
            trayIcon.Text = "Getting carbon intensity data ...";
            trayIcon.Icon = new Icon(SystemIcons.Question, 40, 40);
            trayIcon.Click += new EventHandler(trayIcon_Click);

            // Add menu to tray icon and show it.
            trayIcon.ContextMenu = trayMenu;
            trayIcon.Visible = true;

            Trace.WriteLine("Starting up monitor thread");
            Thread updateThread = new Thread(RunUpdates);
            updateThread.Start();
        }

        void trayIcon_Click(object sender, EventArgs e)
        {
            string target = ConfigurationManager.AppSettings["InfoUrl"];
            System.Diagnostics.Process.Start(target);
        }

        private void RunUpdates()
        {
            Trace.WriteLine("Getting data from config");
            //get data from config file - this will not update dynamically
            string url = ConfigurationManager.AppSettings["DataUrl"];
            Trace.WriteLine(string.Format("DataUrl: {0}" , url));
            decimal lowerLimit;
            string lowerLimitText =ConfigurationManager.AppSettings["lowerLimit"];
            if (!decimal.TryParse(lowerLimitText , out lowerLimit))
            {
                lowerLimit=lowerLimitDefault;
            }
            Trace.WriteLine(string.Format("lowerLimit: {0}", lowerLimit));
            decimal upperLimit;
            string upperLimitText =ConfigurationManager.AppSettings["upperLimit"];
            if (!decimal.TryParse(upperLimitText , out upperLimit))
            {
                upperLimit=upperLimitDefault;
            }
            Trace.WriteLine(string.Format("upperLimit: {0}", upperLimit));
            string lastBand = string.Empty;
            do
            {
                try
                {
                    //try to get the XML
                    Trace.WriteLine(string.Format("Calling data from: {0}", url));
                    var response = GridDataHelper.GetRemoteXml(url);
                    Trace.WriteLine(string.Format("Response: {0}", response));
                    //try to convert into readable object
                    var liveCarbonIntensity = GridDataHelper.LiveCarbonIntensityFromXml(response);
                    //if valid data received
                    if (liveCarbonIntensity != null)
                    {
                        //set tray icon text to be an overview of data
                        string newReadingText = string.Format("{0:0.000} {1} ({2}), Rolling Mean: {3:0.000} ",
                            liveCarbonIntensity.amount, liveCarbonIntensity.units, liveCarbonIntensity.startDateGMT,
                            liveCarbonIntensity.hhRollingMean.value);
                        trayIcon.Text = newReadingText;
                        Trace.WriteLine(string.Format("Reading: {0}", newReadingText));
                        //display an icon depending on 
                        string iconName = string.Empty;
                        if (liveCarbonIntensity.amount <= lowerLimit)
                        {
                            iconName = "green";
                        }
                        else if (liveCarbonIntensity.amount > upperLimit)
                        {
                            iconName = "red";
                        }
                        else
                        {
                            iconName = "amber";
                        }
                        if (!string.IsNullOrEmpty(lastBand) && lastBand != iconName)
                        {
                            trayIcon.BalloonTipTitle = string.Format("Carbon intensity update");
                            trayIcon.BalloonTipText = newReadingText;
                            trayIcon.ShowBalloonTip(5000);
                        }
                        trayIcon.Icon = new Icon(string.Format(@"Resources\{0}.ico", iconName, 32, 32));

                        //data is released every 5 minutes, this will ensure that the 
                        var dateTimeNextRead = liveCarbonIntensity.startDateGMT.AddMinutes(6);
                        var timeBeforeNextRead = dateTimeNextRead.Subtract(DateTime.Now);
                        Trace.WriteLine(string.Format("Next Reading: {0}", dateTimeNextRead.ToString()));
                        Thread.Sleep((int)timeBeforeNextRead.TotalMilliseconds);
                    }
                    else
                    {
                        //data not come back - do something with response
                        trayIcon.Text = response;

                    }
                }
                catch (Exception e)
                {
                    Trace.WriteLine(string.Format("Error making reading.  Error: {0}",  e.Message ));
                    trayIcon.Icon = new Icon(SystemIcons.Error, 40, 40);
                    trayIcon.Text = string.Format("Error making reading");
                    var dateTimeNextRead = DateTime.Now.AddMinutes(1);
                    var timeBeforeNextRead = dateTimeNextRead.Subtract(DateTime.Now);
                    Trace.WriteLine(string.Format("Next attempt: {0}", dateTimeNextRead.ToString()));
                    Thread.Sleep((int)timeBeforeNextRead.TotalMilliseconds);
                }

            } while (true);
        }

    }
}
